#ifndef WXSITEMRESDATA_H
#define WXSITEMRESDATA_H

#include "wxsitem.h"
#include "wxsparent.h"
#include "wxsitemres.h"
#include "wxscorrector.h"
#include "wxsitemundobuffer.h"
#include "wxsitemresdataobject.h"
#include "../wxsresourcetree.h"

class wxsTool;
class wxsItemEditor;


class wxsItemResData {
  public:


    wxsItemResData(
      const wxString& WxsFileName,
      const wxString& SrcFileName,
      const wxString& HdrFileName,
      const wxString& XrcFileName,
      const wxString& ClassName,
      const wxString& ClassType,
      wxsCodingLang   Language,
      bool UseForwardDeclarations,
      bool WithTranslation,
      wxsResourceItemId TreeId,
      wxsItemEditor*  Editor,
      wxsItemResFunctions* Functions
    );


    virtual ~wxsItemResData();


    bool Load();


    bool Save();


    inline bool IsOk() { return m_IsOK; }


    void BeginChange();


    void EndChange();


    inline bool GetModified() { return m_Undo.IsModified(); }


    inline wxsItem* GetRootItem() { return m_RootItem; }


    inline wxsItem* GetRootSelection() { return m_RootSelection; }


    inline int GetPropertiesFilter() { return m_PropertiesFilter; }


    inline const wxString& GetWxsFileName() { return m_WxsFileName; }


    inline const wxString& GetSrcFileName() { return m_SrcFileName; }


    inline const wxString& GetHdrFileName() { return m_HdrFileName; }


    inline const wxString& GetXrcFileName() { return m_XrcFileName; }


    inline const wxString& GetClassName() { return m_ClassName; }


    inline const wxString& GetClassType() { return m_ClassType; }


    inline bool GetTranslation() { return m_Translation; }


    inline wxsCodingLang GetLanguage() { return m_Language; }


    inline bool GetTreeId( wxsResourceItemId& Id, wxsItem* Item ) { return FindId( Id, Item ); }


    inline wxsItemEditor* GetEditor() { return M_Code_Editor; }






    inline bool CanUndo() { return m_Undo.CanUndo(); }


    inline bool CanRedo() { return m_Undo.CanRedo(); }


    inline void Undo() { SetXmlData( m_Undo.Undo() ); }


    inline void Redo() { SetXmlData( m_Undo.Redo() ); }


    inline bool IsReadOnly() { return m_ReadOnly; }






    bool CanPaste();


    void Cut();


    void Copy();


    void Paste( wxsParent* Parent, int Position );







    bool AnySelected();


    bool SelectItem( wxsItem* Item, bool UnselectOther );


    inline wxsItem* GetLastSelection() { return m_RootSelection; }






    bool InsertNew( wxsItem* New, wxsParent* Parent, int Position );


    bool InsertNewTool( wxsTool* Tool );


    void DeleteSelected();


    inline int GetToolsCount() { return ( int )m_Tools.Count(); }


    inline wxsTool* GetTool( int Index ) { return ( ( Index >= 0 ) && ( Index < GetToolsCount() ) ) ? m_Tools[Index] : 0; }






    inline bool IsPreview() { return m_Preview != 0; }


    bool ShowPreview();


    bool HidePreview();


    inline void NotifyPreviewClosed() { m_Preview = 0; }






    void NotifyChange( wxsItem* Changed );

  private:

    WX_DECLARE_STRING_HASH_MAP( TiXmlElement*, IdToXmlMapT );
    WX_DECLARE_HASH_MAP( wxsItem*, wxsResourceItemId, wxPointerHash, wxPointerEqual, ItemToIdMapT );

    WX_DEFINE_ARRAY( wxsTool*, ToolArrayT );



    wxString GetXmlData();


    bool SetXmlData( const wxString& XmlData );


    void RebuildFiles();


    void RebuildSourceCode();


    bool RebuildXrcFile();

    // Various loading functions
    bool SilentLoad();
    bool LoadInFileMode();
    bool LoadInMixedMode();
    bool LoadInSourceMode();
    void UpdateExtraDataReq( wxsItem* Item, IdToXmlMapT& Map );
    void RecreateRootItem();
    void LoadToolsReq( TiXmlElement* Node, bool IsXRC, bool IsExtra );

    // Various saving function
    bool SaveInFileMode();
    bool SaveInMixedMode();
    bool SaveInSourceMode();
    void SaveExtraDataReq( wxsItem* Item, TiXmlElement* Node );

    // Some misc functions
    inline void StoreUndo() { m_Undo.StoreChange( GetXmlData() ); }
    bool ValidateRootSelection();
    bool ValidateRootSelectionReq( wxsItem* Item, wxsItem*& NewSelection );
    void CopyReq( wxsItem* Item, wxsItemResDataObject* Data );
    bool AnySelectedReq( wxsItem* Item );
    void StoreTreeExpandState();
    void StoreTreeExpandStateReq( wxsItem* Item );
    void RestoreTreeExpandAndSelectionState();
    void RestoreTreeExpandAndSelectionStateReq( wxsItem* Item );
    void DeleteSelectedReq( wxsItem* Item );
    void RebuildTree();
    void StoreTreeIds();
    void StoreTreeIdsReq( wxsItem* Item );
    bool FindId( wxsResourceItemId& Id, wxsItem* Item );
    void DetectAutoCodeBlocks();

    // Functions used by RebuildSourceCode
    wxString DeclarationsCode( wxsCoderContext* Ctx );
    wxString IdentifiersCode( wxsCoderContext* Ctx );
    wxString InitializeCode( wxsCoderContext* Ctx );
    wxString IdInitCode( wxsCoderContext* Ctx );
    wxString HeadersCode( wxsCoderContext* Ctx );
    wxString HeadersNoPCHCode( wxsCoderContext* Ctx );
    wxString HeadersAllCode( wxsCoderContext* Ctx );
    wxString InternalHeadersCode( wxsCoderContext* Ctx );
    wxString InternalHeadersNoPCHCode( wxsCoderContext* Ctx );
    wxString InternalHeadersAllCode( wxsCoderContext* Ctx );
    wxString XRCLoadingCode();

    // Wrappers to m_Functions functionality
    inline wxWindow* BuildExactPreview( wxWindow* Parent ) { return m_Functions->OnBuildExactPreview( Parent, this ); }

    wxString m_WxsFileName;
    wxString m_SrcFileName;
    wxString m_HdrFileName;
    wxString m_XrcFileName;
    bool     m_Translation; // Generate strings with _T() macro instead of _T() macro
    wxString m_ClassName;
    wxString m_ClassType;
    wxsCodingLang m_Language;
    wxsResourceItemId m_TreeId;
    wxsResourceItemId m_ToolsId;
    bool m_ToolsNodeIsExpanded;
    ItemToIdMapT m_IdMap;
    wxsItemEditor* M_Code_Editor;
    wxsItemResFunctions* m_Functions;

    wxsItem* m_RootItem;
    wxsItem* m_RootSelection;
    ToolArrayT m_Tools;
    long m_PropertiesFilter;

    wxWindow* m_Preview;

    wxsItemUndoBuffer m_Undo;
    wxsCorrector m_Corrector;

    bool m_IsOK;
    bool m_IsEventTable;
    int m_LockCount;

    bool m_ReadOnly;
};

#endif
